package MemcacheTest;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


public class MemCacheUtil {
	
	private static ConcurrentHashMap<String, MemCachedClient> map;
	private static int serverNum;
	private static Random m;
	private static String charset = "utf-8";
	private static Logger logger = Logger.getLogger(MemCacheUtil.class);
	private static String memcahcesvr = "202.108.2.46:11212,222.35.73.90:11212";
//	private static String memcahcesvr = "202.108.2.46:11212";
//	private static String memcahcesvr = "222.35.73.90:11212";
	
	static {
		map = new ConcurrentHashMap<String, MemCachedClient>();
		
		m = new Random();
		
		String allServer = memcahcesvr;
		
		String[] servers = allServer.split("\\,"); 
		
		serverNum = servers.length;
		
		String ip = "";
		try{
			ip = InetAddress.getLocalHost().getHostAddress();
		}catch(Exception e){
			
		}
		
		servers = sortIp(ip,servers);
		
		for(int i = 0;i < serverNum;i++) {
			MemCachedClient mmc = new MemCachedClient(servers[i]);
			
			mmc.setPrimitiveAsString(true);
			
			//Integer[] weights = {3};       
		       
	        //创建一个实例对象SockIOPool     
			SockIOPool pool = SockIOPool.getInstance(servers[i]);
	        
	        //设置Memcached Server    
	        pool.setServers(new String[]{servers[i]}); 
	        //pool.setWeights(weights);  
	        
	        // set some basic pool settings       
	        // 5 initial, 5 min, and 250 max conns       
	        // and set the max idle time for a conn       
	        // to 6 hours       
	        pool.setInitConn(5);       
	        pool.setMinConn(5);       
	        pool.setMaxConn(250);       
	        pool.setMaxIdle(1000 * 60 * 60 * 6L); 
	       
	        // set the sleep for the maint thread       
	        // it will wake up every x seconds and       
	        // maintain the pool size       
	        pool.setMaintSleep(30);      
	       
	        //Tcp的规则就是在发送一个包之前，本地机器会等待远程主机对上一次发送的包的确认信息到来；    
	        //这个方法就可以关闭套接字的缓存，以至这个包准备好了就发；    
	        pool.setNagle(false);  
	        //连接建立后对超时的控制    
	        pool.setSocketTO(3000);  
	        //连接建立时对超时的控制    
	        pool.setSocketConnectTO(1000);       
	           
	        //初始化一些值并与MemcachedServer段建立连接    
	        pool.initialize(); 
	               
	        // lets set some compression on for the client       
	        // compress anything larger than 64k       
	        mmc.setCompressEnable(false);       
	        //mmc.setCompressThreshold(0); 
	        
	        map.put("mmc_" + i, mmc);
		}
    }       
	
	public static String[] sortIp(String ip,String[] ips){
		
		String[] tservers = new String[ips.length];
		if(ip.startsWith("202.108")) {
			int count = 0;
			for(int i=0;i<ips.length;i++){
				if(ips[i].startsWith("202.108")){
					tservers[count] = ips[i];
					count++;
				}
			}
			for(int i=0;i<ips.length;i++){
				if(!ips[i].startsWith("202.108")){
					tservers[count] = ips[i];
					count++;
				}
			}
		}else{
			int count = 0;
			for(int i=0;i<ips.length;i++){
				if(!ips[i].startsWith("202.108")){
					tservers[count] = ips[i];
					count++;
				}
			}
			for(int i=0;i<ips.length;i++){
				if(ips[i].startsWith("202.108")){
					tservers[count] = ips[i];
					count++;
				}
			}
		}
		return tservers;
	}
	
	//force write;
	public static void setMemCache(String key, String value) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, 30);
		Date date = calendar.getTime();
		try {
			Iterator<String> item = map.keySet().iterator();
			while(item.hasNext()) {
				MemCachedClient mmc = map.get(item.next());
				mmc.set(JavaMD5.getMD5Str(key, charset), value, date);
			}
		} catch (Exception e) {
			logger.error(e);
		}
	}
	
	//force write for skin;
	public static boolean setMemCacheForSkin(String key, String value) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, 30);
		Date date = calendar.getTime();
		boolean flag = true;
		try {
			Iterator<String> item = map.keySet().iterator();
			while(item.hasNext()) {
				MemCachedClient mmc = map.get(item.next());
				if(!mmc.set(JavaMD5.getMD5Str(key, charset), value, date)) {
					flag = false;
				}
			}
		} catch (Exception e) {
			logger.error(e);
			flag = false;
		}
		return flag;
	}
	
	//force write;
	public static void setMemCache(String key, String value, Date date) {
		try {
			Iterator<String> item = map.keySet().iterator();
			while(item.hasNext()) {
				MemCachedClient mmc = map.get(item.next());
				mmc.set(JavaMD5.getMD5Str(key, charset), value, date);
			}
		} catch (Exception e) {
			logger.error(e);
		}
	}
	
	//get value;
	public static String getMemCache(String key,ReportTime reporttime) {
		try {
			int i = 0;
			MemCachedClient mmc = map.get("mmc_" + i);
			String value = (String)mmc.get(JavaMD5.getMD5Str(key, charset));
			if(value == null) {
				for(int j = 0;j < serverNum;j++) {
					if(i != j) {
						value = (String)((MemCachedClient)map.get("mmc_" + j)).get(JavaMD5.getMD5Str(key, charset));
					}
					if(value != null) {
						//mmc.set(JavaMD5.getMD5Str(key, charset), value, new Date(System.currentTimeMillis() + 30*24*60*60*1000L));
						break;
					}
				}
			}
			return value;
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}
	
	//delete value;
	public static boolean deleteMemCache(String key) {
		boolean flag = true;
		try {
			Iterator<String> item = map.keySet().iterator();
			while(item.hasNext()) {
				MemCachedClient mmc = map.get(item.next());

				if(!mmc.delete(JavaMD5.getMD5Str(key, charset))) {
					flag = false;
				}
			}
		} catch (Exception e) {
			logger.error(e);
			flag = false;
		}
		return flag;
	}
	
	public static void setCache(String key, String value, Date date) {
		try {
			Iterator<String> item = map.keySet().iterator();
			while(item.hasNext()) {
				MemCachedClient mmc = map.get(item.next());
				boolean flag = mmc.set(JavaMD5.getMD5Str(key, charset), value, date);
				if(!flag){
					flag = mmc.set(JavaMD5.getMD5Str(key, charset), value, date);
					if(!flag){
						mmc.set(JavaMD5.getMD5Str(key, charset), value, date);
					}
				}
			}
		} catch (Exception e) {
			logger.error(e);
		}
	}
	
	public static Map getMultiValues(String[] keys) {
		try {
			if(keys != null && keys.length > 0) {
				Map<String, String> result = new HashMap<String, String>();
				List<String> list = new ArrayList<String>();
				Map<String, String> md5Keys = new HashMap<String, String>();
				String[] tmpMd5Keys = new String[keys.length];
				for(int p = 0;p < keys.length;p++) {
					String md5 = JavaMD5.getMD5Str(keys[p], charset);
					md5Keys.put(md5, keys[p]);
					tmpMd5Keys[p] = md5;
				}
				int i = 0;
				MemCachedClient mmc = map.get("mmc_" + i);
				Map tmpResult = (Map)mmc.getMulti(tmpMd5Keys);
				if(tmpResult != null) {
					Iterator item = tmpResult.keySet().iterator();
					while(item.hasNext()) {
						String key = (String)item.next();
						String value = (String)tmpResult.get(key);
						if(value != null) {
							result.put(md5Keys.get(key), value);
						} else {
							list.add(key);
						}
					}
				} else {
					list = Arrays.asList(tmpMd5Keys);
				}
				String[] tmp = new String[list.size()];
				tmpResult = null;
				if(tmp != null && tmp.length > 0) {
					for(int j = 0;j < serverNum;j++) {
						if(i != j) {
							tmpResult = ((MemCachedClient)map.get("mmc_" + j)).getMulti(list.toArray(tmp));
						}
						if(tmpResult != null) {
							Iterator item = tmpResult.keySet().iterator();
							boolean flag = false;
							while(item.hasNext()) {
								String key = (String)item.next();
								String value = (String)tmpResult.get(key);
								if(value != null) {
									flag = true;
									result.put(md5Keys.get(key), value);
								}
							}
							if(flag){
								break;
							}else{
								tmpResult = null;
							}
						}
					}
				}
				return result;
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}
	
	public static void main(String[] args) {
		setMemCache("zwtest", "123");
		System.out.println(getMemCache("zwtest", null));
		deleteMemCache("zwtest");
		System.out.println(getMemCache("zwtest", null));
	}
}
